<template>
    <Modal
        class="org-tree"
        v-model="visible"
        :closable="false"
        :mask-closable="false"
        width="860">
        <div class="org-tree-head" slot="header">
            <span class="org-tree-close" title="关闭"
                @click="closeOrgTree"
            ></span>
            <h3 class="org-tree-title">组织机构选择窗口</h3>            
        </div>
        <div class="org-tree-main">
            <div class="org-tree-oper">
                <a class="otre-oper-save"
                    @click="saveOrgTree"
                ><i></i>保存并关闭</a>
            </div>
            <div class="org-tree-cont">
                <div class="org-tree-sect">
                    <div class="otre-sect-head">
                        <h3 class="otre-sect-title">组织机构</h3>
                    </div>
                    <div class="otre-sect-main">
                        <div class="otre-sect-cont">
                            <Tree ref="tree"
                                :data="treeData"
                                @on-select-change="selectChange"
                                @on-check-change="checkChange"
                                show-checkbox></Tree>
                        </div>
                    </div>
                </div>
                <div class="org-tree-split"></div>
                <div class="org-tree-sect user">
                    <div class="otre-sect-head">
                        <h3 class="otre-sect-title">用户列表</h3>
                        <div class="otre-sect-sear">
                            <i title="搜索用户"
                                @click="searchUser"
                            ></i>
                            <input type="text" placeholder="简全拼及用户名"
                                v-model="searKey"
                                @keyup="searchUser"
                            >                        
                        </div>
                    </div>
                    <div class="otre-sect-main">
                        <div class="otre-sect-cont">
                            <ul class="otre-sect-list">
                                <li 
                                    v-for="(item, index) in waitList"
                                    :class="['otre-sect-item', {'seled': item.seledFlag}]"
                                    :key="index"
                                    @click="selectItem('wait', index, $event)"
                                    @dblclick="addSingleItem(index)"
                                >
                                    <a class="otst-item-name" :title="item.name">{{ item.name }}</a>
                                </li>
                            </ul>
                        </div>
                    </div>
                </div>
                <div class="org-tree-split">
                    <a class="add" title="将选中的已选择人员移除"
                        @click="addMultiItem"
                    ></a>
                    <a class="remove" title="将选中人员添加到已选择列表"
                        @click="removeMultiItem"
                    ></a>
                </div>
                <div class="org-tree-sect seled">
                    <div class="otre-sect-head">
                        <h3 class="otre-sect-title">已选择项</h3>
                        <div class="otre-sect-sort">
                            <a class="up" title="向上"
                                @click="sortUp"
                            ></a>
                            <a class="down" title="向下"
                                @click="sortDown"
                            ></a>                      
                        </div>
                    </div>
                    <div class="otre-sect-main">
                        <div class="otre-sect-cont">
                            <ul class="otre-sect-list">
                                <li
                                    v-for="(item, index) in seledList"
                                    :class="['otre-sect-item', {'seled': item.seledFlag}]"
                                    :key="index"
                                    @click="selectItem('seled', index, $event)"
                                    @dblclick="removeSingleItem(index)"
                                >
                                    <i class="otst-item-rm" title="移除"
                                        @click="removeSingleItem(index)"
                                    ></i>
                                    <a class="otst-item-name" :title="item.name">{{ item.name }}</a>                                    
                                </li>
                            </ul>
                        </div>
                    </div>
                </div>
            </div>
        </div>
        <div class="org-tree-foot" slot="footer"></div>
    </Modal>
</template>
<script>
import orgTreeApi from '../../api/orgtree/orgTree.js'

export default {
    name: "orgTree",
    props: {
        visible: {
            type: Boolean,
            default: false
        },
        option: {
            type: Object,
            default(){
                return {};
            }
        },
        result: {
            default(){
                return {};
            }
        }
    },
    data(){
        return {
            config: {
                deptFlag: true,
                deptLimit: false,
                userFlag: true,
                singleFlag: false,
            },
            searFlag: false,
            searKey: '',            
            waitFlag: false,
            waitList: [],
            seledFlag: false,
            seledList: [],
            nodeIdMap: {},
            deptChkedList: [],
            treeData: []
        }
    },
    watch: {
        visible(val){
            if(val){
                this.fillInitData();
                this.getTreeData();        
            }
        }
    },
    mounted(){
        if(this.option){
            Object.assign(this.config, this.option);
        }
    },
    methods: {
        closeOrgTree(){
            this.$emit('update:visible', false);
        },
        saveOrgTree(){
            this.closeOrgTree();
            this.$emit('on-save', this.seledList);
        },
        fillInitData(){
            let _self = this,
                _result = this.result,
                _deptChkedList = this.deptChkedList,
                _itemList = [];
            if(_result instanceof Array && _result.length > 0){
                let _item = null;       
                _result.forEach((item, index) => {
                    _item = _self.getDefaultItem();
                    Object.assign(_item, item);
                    _itemList.push(_item);
                    if(_item.type == 'dept' && _deptChkedList.join(',').indexOf(_item.id) == -1){
                        _deptChkedList.push(_item.id);
                    }
                });
            }
            this.addItemToSeledList(_itemList);
        },
        parseData(nodes){
            let _config = this.config,
                _deptChkedStr = '',
                _tmpMap = {},
                _node = null,
                _nodeList = [];
            if(!nodes || !(nodes instanceof Array) || nodes.length == 0){
                return [];
            }
            _deptChkedStr = this.deptChkedList.length > 0 ? this.deptChkedList.join(',') : '';
            for(let i = 0, _len = nodes.length; i < _len; i++){
                _tmpMap[nodes[i]['id']] = nodes[i];
            }
            this.nodeIdMap = _tmpMap;
            for(let i = 0, _len = nodes.length; i < _len; i++){
                let _node = nodes[i],
                    _parent = _tmpMap[_node.pid];
                _node.title = _node.name;
                _node.disableCheckbox = !_config.deptFlag || (_config.deptFlag && _config.deptLimit && _node.code.length > 6);
                this.$set(_node, 'checked', _config.deptFlag && !!_deptChkedStr && _deptChkedStr.indexOf(_node.id) > -1);
                if(_parent && _node.id != _node.pid){
                    let _child = _parent.children;
                    if(!_child){
                        _child = _parent.children = [];
                    }                   
                    _child.push(_node);
                }else{
                    _nodeList.push(_node);
                }
            }
            return _nodeList;
        },
        getTreeData(){
            orgTreeApi.getOrgAndDeptList()
                .then(res => {
                    let _treeData = this.parseData(res.data);
                    if(_treeData.length > 0){
                        _treeData[0].expand = true;
                        _treeData[0].disableCheckbox = true;
                    }
                    this.treeData = _treeData;
                })
                .catch(error => {
                    console.log(error);
                });
        },
        addItemToWaitList(itemList = []){
            if(!itemList || !(itemList instanceof Array) || !itemList.length){
                return false;
            }
            let _self = this,
                _nodeIdMap = this.nodeIdMap,
                _item = null,
                _itemList = [];
            itemList.forEach((item, index) => {
                _item = _self.getDefaultItem();
                _item.id = item.id;
                _item.name = item.name;
                _item.type = item.type;
                if(item.deptId){
                    let _dept = null,
                        _parent = null;
                    _dept = _nodeIdMap[item.deptId];
                    while(_dept && _dept.code.length > 6){
                        _dept = _nodeIdMap[_dept.pid];
                    }
                    if(_dept){
                        _item.deptId = _dept.id;
                        _item.deptName = _dept.name;
                        if(_dept.code.length == 6){
                            _parent = _nodeIdMap[_dept.pid];
                            if(_parent && _parent.type == 'dept'){
                                _item.superDeptId = _parent.id;
                                _item.superDeptName = _parent.name;
                            }
                        }
                    }    
                }
                _item.userMdn = item.userMdn;
                _itemList.push(_item);
            });
            this.waitList = _itemList;
        },
        uncheckTreeNodeById(id){
            if(!id){
                return false;
            }
            let _node = this.nodeIdMap[id];
            _node.checked = false;
            if(_node.indeterminate){
                _node.indeterminate = false;
            }
            if(_node.children instanceof Array && _node.children.length > 0){
                this.uncheckTreeNodeList(_node.children);
            }
        },
        uncheckTreeNodeList(nodeList){
            let _self = this;            
            if(nodeList instanceof Array && nodeList.length > 0){
                nodeList.forEach((node, index) => {
                    _self.uncheckTreeNodeById(node.id);
                });
            }
        },
        selectChange(nodes){
            if(!nodes || !(nodes instanceof Array) || !nodes.length){
                return false;
            }
            let _node = nodes[0];
            if(_node.type != "dept"){
                return false;
            }
            orgTreeApi.getUserListByDeptId(_node.id)
                .then(res => {
                    this.addItemToWaitList(res.data);
                })
                .catch(error => {
                    console.log(error);
                });
        },
        checkChange(nodes){
            let _self = this,
                _config = this.config,
                _nodeIdMap = this.nodeIdMap,
                _tmpMap = {},
                _nodeList = [],
                _item = null,
                _itemList = [],
                [..._oldSeledList] = this.seledList,
                _newSeledList = [];
            //清空已选择项缓存列表
            this.deptChkedList = [];
            //未选中任何节点
            if(nodes.length == 0){
                this.seledList = [];
                return false;
            }
            //过滤掉重复的子部门
            nodes.forEach((node, index) => {
                _tmpMap[node.id] = node;
            });
            nodes.forEach((node, index) => {
                if(!_tmpMap[node.pid]){
                    _nodeList.push(node);
                }
            });
            //如果是单选
            if(_config.singleFlag){
                _nodeList.forEach((node, index) => {
                    if(!_self.getItemFromListById(node.id, _oldSeledList) && _newSeledList.length == 0){
                        let _item = this.renderItemByNode(node);
                        if(_item){
                            _self.deptChkedList.push(_item.id);
                            _newSeledList.push(_item);
                        }
                    }else{
                        _self.uncheckTreeNodeById(node.id);
                    }
                });
            }else{ //如果是多选
                _oldSeledList.forEach((item, index) => {
                    if(item.type == 'dept' && !_self.getItemFromListById(item.id, _nodeList)){
                        return true;
                    }else{
                        _self.deptChkedList.push(item.id);
                        _newSeledList.push(item);
                    }
                });
                _nodeList.forEach((node, index) => {
                    if(!_self.getItemFromListById(node.id, _newSeledList)){
                        let _item = this.renderItemByNode(node);
                        if(_item){
                            _self.deptChkedList.push(_item.id);
                            _newSeledList.push(_item);
                        }                
                    }
                }); 
            }
            this.seledList = _newSeledList;
        },
        searchUser(){
            let _key = this.searKey;
            if(!_key){
                this.waitList = [];
                return false;
            }
            if(this.searFlag){
                return false;
            }else{
                this.searFlag = true;
            }
            orgTreeApi.getUserListByKey(_key)
                .then(res => {
                    if(_key){
                        this.addItemToWaitList(res.data);
                    }
                    this.searFlag = false;
                })
                .catch(error => {
                    this.searFlag = false;
                    console.log(error);
                });
        },
        getItemFromListById(id = '', itemList = []){
            let _obj = null;
            if(!id || !itemList || !(itemList instanceof Array) || itemList.length == 0){
                return _obj;
            }
            itemList.forEach((item, index) => {
                if(item.id == id ){
                    _obj = {
                        index: index,
                        item: item
                    };
                }
            });
            return _obj;
        },
        getSeledItemIndex(type = 'wait'){
            let _index = -1,
                _itemList = type == 'wait' ? this.waitList : this.seledList;
            _itemList.forEach((item, index) => {
                if(item.seledFlag){
                    _index = index;
                    return false;
                }
            });
            return _index;
        },
        getDefaultItem(){
            return {
                'id': '',
                'name': '',
                'type': '',
                'deptId': '',
                'deptName': '',
                'superDeptId': '',
                'superDeptName': '',
                'userMdn': '',
                'seledFlag': false
            };
        },
        renderItemByNode(node){
            if(!node){
                return false;
            }
            let _nodeIdMap = this.nodeIdMap,
                _item = this.getDefaultItem();
            _item.id = node.id;
            _item.name = node.name;
            _item.type = node.type;
            if(node.type == 'dept'){
                let _parent = null;
                _item.deptId = node.id;
                _item.deptName = node.name;
                _parent = _nodeIdMap[node.pid];                 
                if(_parent && _parent.type == 'dept'){
                    _item.superDeptId = _parent.id;
                    _item.superDeptName = _parent.name;           
                }
            }
            _item.userMdn = node.userMdn;
            return _item;
        },
        selectItem(type = 'wait', index, event){
            let _seledIndex = -1,
                _item = null,
                _itemList = type == 'wait' ? this.waitList : this.seledList;
            if(isNaN(index) || index < 0){
                return false;
            }
            _item = _itemList[index];
            if(!_item){
                return false;
            }
            if(_item.seledFlag){
                _item.seledFlag = false;
            }else if(event.shiftKey){
                _seledIndex = this.getSeledItemIndex(type);
                if(_seledIndex >= 0){
                    let _start = _seledIndex > index ? index : _seledIndex,
                        _end = index > _seledIndex ? index : _seledIndex;
                    _itemList.forEach((item, index) => {
                        if(index >= _start && index <= _end){
                            item.seledFlag = true;
                        }else{
                            item.seledFlag = false;
                        }
                    });
                }else{
                    _item.seledFlag = true;
                }
            }else if(event.ctrlKey){
                _item.seledFlag = true;
            }else{
                let _index = index;
                _item.seledFlag = true;
                _itemList.forEach((item, index) => {
                    if(index != _index){
                        item.seledFlag = false;
                    }
                });
            }
        },
        mouseDownItem(type = 'wait', index){
            if(isNaN(index) || index < 0){
                return false;
            }
            if(type == 'wait'){
                this.waitFlag = true;
            }else{
                this.seledFlag = true;
            }
        },
        mouseOverItem(type = 'wait', index){
            if(isNaN(index) || index < 0){
                return false;
            }
            if(type == 'wait' && this.waitFlag){
                this.waitList[index].seledFlag = true;
            }else if(type == 'seled' && this.seledFlag){
                this.seledList[index].seledFlag = true;
            }else{
                return true;
            }
        },
        mouseUpItem(type = 'wait', index){
            this.waitFlag = false;
            this.seledFlag = false;
        },
        getSeledItemById(id){
            let _item = null;
            this.seledList.forEach((item, index) => {
                if(item.id == id){
                    _item = item;
                }              
            });
            return _item;
        },
        addItemToSeledList(itemList = []){
            let _self = this,
                _config = this.config,
                _itemList = [],
                _seledList = [];
            if(itemList instanceof Array && itemList.length > 0){
                itemList.forEach((item, index) => {
                    if(!_self.getSeledItemById(item.id)){
                        _itemList.push(item);
                    }
                });
                if(_itemList.length > 0){
                    if(_config.singleFlag){
                        _seledList.push(_itemList[0]);
                    }else{
                        _seledList= this.seledList.concat(_itemList);
                    }
                    this.seledList = _seledList;
                }
            }else{
                this.seledList = [];
            }
        },
        addSingleItem(index){
            if(isNaN(index) || index < 0){
                return false;
            }
            let _config = this.config,
                item = null,
                _item = null,           
                _itemList = [];
            if(!_config.userFlag){
                return false;
            }
            item = this.waitList[index];
            _item = this.getDefaultItem();
            Object.assign(_item, item);
            _itemList.push(_item);
            this.addItemToSeledList(_itemList);
        },
        addMultiItem(){
            let _self = this,
                _config = this.config,
                _item = null,
                _itemList = [];
            if(!_config.userFlag){
                return false;
            }
            this.waitList.forEach((item, index) => {
                if(item.seledFlag){
                    _item = _self.getDefaultItem();
                    Object.assign(_item, item);
                    _itemList.push(_item);
                }
            });
            this.addItemToSeledList(_itemList);
        },
        removeSingleItem(index){
            if(isNaN(index) || index < 0){
                return false;
            }
            let _item = this.seledList.splice(index, 1)[0];
            if(_item && _item.type == 'dept'){
                this.uncheckTreeNodeById(_item.id);
            }
        },
        removeMultiItem(){
            let _self = this,
                _seledList = this.seledList;
            _seledList.forEach((item, index) => {
                if(item.seledFlag){
                    let _item = _seledList.splice(index, 1)[0];
                    if(_item && _item.type == 'dept'){
                        _self.uncheckTreeNodeById(_item.id);
                    }
                }
            });
        },
        sortUp(){
            let _seledList = this.seledList,
                [..._sortList] = _seledList,
                _index = 0,
                _obj = null,
                _item = null,                
                _idList = [];
            _seledList.forEach((item, index) => {
                if(item.seledFlag){
                    _idList.push(item.id);
                }
            });
            if(_idList.length == 0){
                return false;
            }
            for(let i = 0, _len = _idList.length; i < _len; i++){
                _obj = this.getItemFromListById(_idList[i], _sortList);
                if(_obj){
                    _index = _obj.index;
                    if(_index == 0){
                        _item = _sortList.shift();
                        _sortList.push(_item);
                    }else{
                        _item = _sortList[_index - 1];
                        _sortList[_index - 1] = _sortList[_index];
                        _sortList[_index] = _item;
                    }
                }
            }
            this.seledList = _sortList;
        },
        sortDown(){
            let _seledList = this.seledList,
                _len = _seledList.length,
                [..._sortList] = _seledList,
                _index = 0,
                _obj = null,
                _item = null,                
                _idList = [];
            _seledList.forEach((item, index) => {
                if(item.seledFlag){
                    _idList.push(item.id);
                }
            });
            if(_idList.length == 0){
                return false;
            }
            for(let i = _idList.length - 1; i >= 0; i--){
                _obj = this.getItemFromListById(_idList[i], _sortList);
                if(_obj){
                    _index = _obj.index;
                    if(_index == _len - 1){
                        _item = _sortList.pop();
                        _sortList.unshift(_item);
                    }else{
                        _item = _sortList[_index + 1];
                        _sortList[_index + 1] = _sortList[_index];
                        _sortList[_index] = _item;
                    }
                }
            }
            this.seledList = _sortList;
        }
    }
}
</script>
<style lang='scss' scoped>
    .org-tree-head{
        height: 36px;
        padding: 6px 15px 6px 20px;
        background: #EAEAEA;
        border-radius: 6px 6px 0 0;
        .org-tree-title{
            height: 24px;
            line-height: 24px;
            font-weight: bold;
            font-size: 14px;
            color: #1C1C1C;
        }
        .org-tree-close{
            float: right;
            width: 10px;
            height: 10px;
            margin-top: 7px;
            background: url('../../../static/img/icon-close-gray-10x10.png') 0 0 no-repeat;
            cursor: pointer;
        }
    }
    .org-tree-main{
        padding: 20px;
        .org-tree-oper{
            height: 36px;
            .otre-oper-save{
                float: right;
                width: 120px;
                height: 36px;
                line-height: 24px;
                padding: 6px 0 6px 16px;
                background: #45B636;
                border-radius: 4px;
                font-size: 14px;
                color: #fff;
                cursor: pointer;
                i{
                    float: left;
                    width: 15px;
                    height: 15px;
                    margin: 4px 8px 0 0;
                    background: url('../../../static/img/icon-save-white-15x15.png') 0 0 no-repeat;
                }
            }
        }
        .org-tree-cont{
            margin-top: 20px;
            overflow: hidden;
            .org-tree-sect{
                float: left;
                width: 290px;
                height: 415px;
                border: #CBCBCB 1px solid;
                .otre-sect-head{
                    height: 30px;            
                    padding: 0 8px 0 10px;
                    border-bottom: #59B0F5 2px solid;       
                    .otre-sect-title{
                        float: left;
                        height: 28px;
                        line-height: 28px;
                        font-size: 14px;
                        color: #59B0F5;
                    }
                    .otre-sect-sear{
                        height: 28px;
                        margin-left: 70px;
                        padding: 4px 0 4px 8px;
                        border-left: #CBCBCB 1px solid;
                        input{
                            width: 98px;
                            height: 20px;
                            line-height: 20px;
                            border: 0;
                            outline: 0;
                            font-size: 14px;
                            color: #999;
                        }
                        i{
                            float: right;
                            width: 20px;
                            height: 20px;
                            background: url('../../../static/img/icon-sear-gray-19x19.png') 0 0 no-repeat;
                            cursor: pointer;
                        }
                    }
                    .otre-sect-sort{
                        height: 28px;
                        padding: 9px 0;
                        a{
                            float: left;
                            width: 20px;
                            height: 10px;
                            margin-left: 6px;
                            cursor: pointer;
                            &.up{
                                background: url('../../../static/img/icon-arrow-gt-20x10.png') 0 0 no-repeat;
                            }
                            &.down{
                                background: url('../../../static/img/icon-arrow-gb-20x10.png') 0 0 no-repeat;
                            }
                        }
                    }
                }
                .otre-sect-main{
                    padding: 5px;
                    .otre-sect-cont{
                        height: 375px;
                        overflow: auto;
                        user-select: none;
                        .otre-sect-list{
                            padding: 6px 8px 0;
                            .otre-sect-item{
                                height: 30px;
                                margin-bottom: 6px;
                                padding: 3px 12px 3px 10px;
                                background: #F3F3F3;
                                border: #EDEDED 1px solid;
                                border-radius: 2px;
                                cursor: pointer;
                                .otst-item-name{
                                    display: block;
                                    height: 24px;
                                    line-height: 24px;
                                    margin-right: 30px;
                                    font-size: 14px;
                                    color: #333;
                                    overflow: hidden;
                                }
                                .otst-item-rm{
                                    float: right;
                                    width: 10px;
                                    height: 10px;
                                    margin-top: 6px;
                                    background: url('../../../static/img/icon-close-gray-10x10.png') 0 0 no-repeat;
                                }
                                &.seled{
                                    background: #269AF3;
                                    border: #1785D9 1px solid;
                                    .otst-item-name{
                                        color: #fff;
                                    }
                                    .otst-item-rm{
                                        background: url('../../../static/img/icon-close-white-10x10.png') 0 0 no-repeat;
                                    }
                                }
                            }
                        }
                    }
                }
                &.user,&.seled{
                    width: 234px;
                }
                &.user .otre-sect-title{
                    min-width: 70px;
                }
                &.seled .otre-sect-title{
                    color: #45B636;
                }
            }
            .org-tree-split{
                float: left;
                width: 30px;
                height: 415px;
                padding-top: 164px;
                a{
                    display: block;
                    width: 13px;
                    height: 26px;
                    margin: 0 auto;
                    cursor: pointer;
                    &.add{
                        background: url('../../../static/img/icon-arrow-gr-13x26.png') 0 0 no-repeat;
                    }
                    &.remove{
                        margin-top: 20px;
                        background: url('../../../static/img/icon-arrow-gl-13x26.png') 0 0 no-repeat;
                    }
                }
            }
        }
    }
</style>
<style lang='scss'>
    .org-tree{
        .ivu-modal-header{
            padding: 0;
            border-bottom: 0;
        }
        .ivu-modal-body{
            padding: 0;
        }
        .ivu-modal-footer{
            padding: 0;
            border-top: 0;
        }
    }
</style>